/***************************************************
 * This file contains code related to decoding the
 * radio receiver signals.
 ***************************************************/
#include <msp430x26x.h>
#include "Radio.h"

// Defines
#define CAP_INT_THROTTLE TBIV_TBCCR3
#define CAP_INT_YAW TBIV_TBCCR4
#define CAP_INT_ROLL TBIV_TBCCR5
#define CAP_INT_PITCH TBIV_TBCCR6

// Macros for quick radio receiver interrupt handling
#define DIFF(a,b,max) ((a >= b) ? (a-b) : (max-b+a+1))
#define UPDATE_SERVO(time,servo,edge)\
{\
	if (edge)\
	{\
		servo.servoIn1 = time;\
	}\
	else\
	{\
		servo.servoIn2 = time;\
		servo.dutyCycle = DIFF(servo.servoIn2,servo.servoIn1,39999);\
	}\
}

// Function declarations
__interrupt void servoPWM_in(void);
__interrupt void timerB_overflow(void);
 
// Public variables
volatile RadioServoState RadioCh1; // Roll
volatile RadioServoState RadioCh2; // Pitch
volatile RadioServoState RadioCh3; // Throttle
volatile RadioServoState RadioCh4; // Yaw
 
/***************************************************
 * Initialize the data structures for the radio receiver
 * module.
 ***************************************************/
void RadioInit(void)
{
	// Init channel 1
	RadioCh1.servoIn1 = 0;
	RadioCh1.servoIn2 = 0;
	RadioCh1.dutyCycle = 0;
	
	// Init channel 2
	RadioCh2.servoIn1 = 0;
	RadioCh2.servoIn2 = 0;
	RadioCh2.dutyCycle = 0;
	
	// Init channel 3
	RadioCh3.servoIn1 = 0;
	RadioCh3.servoIn2 = 0;
	RadioCh3.dutyCycle = 0;
	
	// Init channel 4
	RadioCh4.servoIn1 = 0;
	RadioCh4.servoIn2 = 0;
	RadioCh4.dutyCycle = 0;
}

/***************************************************
 * ISR: TBIV (timer B1 interrupt vector) servo PWM in
 ***************************************************/
//interrupt signal set by incoming radio signal going high or low
#pragma vector=TIMERB1_VECTOR
__interrupt void servoPWM_in(void)
{
	// Figure out which channel interrupted and update that command
	switch (TBIV)
	{
		case CAP_INT_THROTTLE:	// RC Ch3 - Throttle
		{
			UPDATE_SERVO(TBCCR3,RadioCh3,(TBCCTL3 & CCI));
			break;
		}
		case CAP_INT_YAW:		// RC Ch4 - Yaw
		{
			UPDATE_SERVO(TBCCR4,RadioCh4,(TBCCTL4 & CCI));
			break;
		}
		case CAP_INT_ROLL:		// RC Ch1 - Roll
		{
			UPDATE_SERVO(TBCCR5,RadioCh1,(TBCCTL5 & CCI));
			break;
		}
		case CAP_INT_PITCH:		// RC Ch2 - Pitch
		{
			UPDATE_SERVO(TBCCR6,RadioCh2,(TBCCTL6 & CCI));
			break;
		}
	}
}
